package com.wangyukai.jmonitor.plugin;

import com.jcraft.jsch.*;
import com.wangyukai.jmonitor.entity.MyUserInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class DeployPlugin {

    private final int CONNECT_TIMEOUT = 3000;
    private String username;
    private String host;
    private String password;
    private int port;
    private final JTextArea log_txtarea;

    private Logger logger = LoggerFactory.getLogger(DeployPlugin.class);

    public DeployPlugin(String host, String username, String password, int port, JTextArea log_txtarea) {
        this.username = username;
        this.host = host;
        this.port = port;
        this.password = password;
        this.log_txtarea = log_txtarea;
    }

    public static void main(String[] args) {
        DeployPlugin deployPlugin = new DeployPlugin("192.168.50.63", "wangyukai", "19841117", 22, null);
        deployPlugin.executeCommand("8520", "skygis-0.0.9-SNAPSHOT.jar", "F:\\deployer\\", "/home/wangyukai/JAVA", "");
    }

    private void log(String msg){
        logger.info(msg);
        if(this.log_txtarea != null){
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    log_txtarea.setText(log_txtarea.getText() + "\r\n" +msg);
                }
            });
        }
    }

    private void logerror(String msg, Throwable throwable){
        logger.error(msg, throwable);
        if(this.log_txtarea != null){
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    String message = "\r\n" +msg + "\r\n" + throwable.getMessage();
                    log_txtarea.setText(log_txtarea.getText() + message);
                }
            });
        }
    }

    public List<String> remoteExecute(Session session, String command) throws JSchException {
        log(">>>>> " +  command);
        List<String> resultLines = new ArrayList<>();
        ChannelExec channel = null;
        try {
            channel = (ChannelExec) session.openChannel("exec");
            channel.setCommand(command);
            InputStream input = channel.getInputStream();
            channel.connect(CONNECT_TIMEOUT);
            try {
                byte[] cache = new byte[1024 * 10];
                int len = 0;
                while ((len = input.read(cache)) != -1) {
                    String inputLine = new String(cache, 0, len);
                    resultLines.add(inputLine);
                }
            } finally {
                if (input != null) {
                    try {
                        input.close();
                    } catch (Exception e) {
                        logerror("JSch inputStream close error:", e);
                    }
                }
            }
        } catch (Exception e) {
            logerror("cxecption:", e);
        } finally {
            if (channel != null) {
                try {
                    channel.disconnect();
                } catch (Exception e) {
                    logerror("JSch channel disconnect error:", e);
                }
            }
        }
        return resultLines;
    }

    public List<String> shellExecute(Session session, String command) throws Exception {
        log(">>>>>" +  command);
        ChannelShell channel = (ChannelShell) session.openChannel("shell");
        channel.setPtyType("dump");
        channel.setPty(true);
        channel.connect();
        InputStream inputStream = channel.getInputStream();
        OutputStream outputStream = channel.getOutputStream();
        Thread.sleep(1000);
        outputStream.write((command + "\n").getBytes());
        Thread.sleep(1000);
        outputStream.flush();

        List<String> result = new ArrayList<>();
        byte[] cache = new byte[1024 * 10];
        int len = 0;
        Thread.sleep(2000);
        while ((len = inputStream.read(cache)) != -1) {
            String inputLine = new String(cache, 0, len);
            result.add(inputLine);
            if(len < cache.length){
                break;
            }
        }
        inputStream.close();
        outputStream.close();
        return result;
    }


    public int executeCommand(String jarport, String jarname, String jarpath, String deployjar, String backfilename) {
        int returnCode = 0;
        JSch jsch = new JSch();
        MyUserInfo userInfo = new MyUserInfo();
        Session session = null;
        try {
            // Create and connect session.
            session = jsch.getSession(username, host, port);
            session.setPassword(password);
            session.setUserInfo(userInfo);
            session.connect();
            // Create and connect channel.
            // 取得端口的pi
            String command = "lsof -i:" + jarport + " | awk '{print $2}' | tail -n +2 ";
            List<String> pid_list = remoteExecute(session, command);

            // kill对应端口进程
            if (pid_list.size() == 1) {
                // kill进程
                remoteExecute(session, "kill -9 " + pid_list.get(0).trim());
            }
            if(StringUtils.isEmpty(backfilename)){
                backfilename = jarname;
            }

            // 备份文件
            remoteExecute(session, "mv " + deployjar + "/" + backfilename + " " + deployjar + "/back/" + jarname + "_" +   new SimpleDateFormat("yyyyMMddhhmmss").format(new Date()));

            // 上传文件
            ChannelSftp sftpchannel = (ChannelSftp) session.openChannel("sftp");
            sftpchannel.connect();
            sftpchannel.cd(deployjar);

            File file = new File(jarpath + File.separator + jarname);
            try {
                FileInputStream newfilein = new FileInputStream(file);
                sftpchannel.put(newfilein, jarname);
            } catch (FileNotFoundException e) {
                logerror("文件不存在-->" + deployjar, e);
            } catch (SftpException e) {
                logerror("sftp异常-->", e);
            }

            log(deployjar + "文件上传成功");


//            List<String> startuplog = remoteExecute(session, "nohup java -jar " + deployjar + "/" + jarname + " > load2.log 2>&1 &");
            List<String> startuplog = shellExecute(session, "nohup java -jar " + deployjar + "/" + jarname + " > load2.log 2>&1 &");
            logger.trace(startuplog.toString());

            sftpchannel.disconnect();

        } catch (Exception e) {
            logerror("预期外异常", e);
        } finally {
            if (session != null) session.disconnect();
        }
        return returnCode;
    }
}
